﻿(*   Copyright 2011 Alexander Omelchuk
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *)

namespace Lisp
open System
open System.Text
open System.Reflection

[<AutoOpen>]
module Helpers =
  let eq = function
  | Id x, Id y when x=y -> true
  | x, y -> LanguagePrimitives.PhysicalEquality x y

  let rec toStr = function
  | Val x -> sprintf "%A" x
  | Id id -> if Char.IsLetter(id.[0]) then id else sprintf "|%s|" id
  | Lst(x,xs) ->
    let xs, cdr =
      foldC (fun (sb:StringBuilder) expr -> sb.AppendFormat(" {0}", toStr expr))
            (new StringBuilder())
            xs
    sprintf "(%s%A%s)" (toStr x) xs (match cdr with |Nil -> "" |x -> sprintf " . %s" (toStr x))

  // <summary>Raises error about expression</summary>
  let inline raiseExprError (message:string) expr =
    raise (EvalException(String.Format(message, toStr expr)))

  let ofSeqMethodInfo = Assembly.GetExecutingAssembly().GetType("Lisp.Lst").GetMethod("ofSExprSeq")